﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NCP.Recruiting.ApplicationServices.Interfaces;
using NCP.Recruiting.ApplicationServices.Messaging.Jobpositions;
using NCP.Recruiting.Domain.Aggregates.Jobpositions;
using NCP.Recruiting.ApplicationServices.ModelConversions;
using NCP.Recruiting.ApplicationServices.Messaging;
using NCP.Recruiting.ApplicationServices.ViewModels;
using NCP.Recruiting.ApplicationServices.Contracts;
using NCP.Infrastructure.Common;
using NCP.Recruiting.Domain.Shared;
using System.Linq.Expressions;
using NCP.Recruiting.ApplicationServices.Shared;
using NCP.Infrastructure.Common.Specification;

namespace NCP.Recruiting.ApplicationServices.Implementations
{
    public class JobPositionAppService : IJobPositionAppService
    {
        private readonly IJobPositionRepository _jobPositionRepository;

        private const String _dateFormat = "yyyy/MM/dd";
        private const String _dateFormatTime = "yyyy/MM/dd HH:mm:ss";

        public JobPositionAppService(IJobPositionRepository jobPositionRepository)
        {
            _jobPositionRepository = jobPositionRepository;
        }

        #region Create
        public CreateJobPositionResponse CreateJobPosition(CreateJobPositionRequest request)
        {
            var response = new CreateJobPositionResponse();
            try
            {
                var entity = request.JobPositionForm.CopyItem<IJobPositionCommand, JobPosition>();
                entity.GenerateNewIdentity();
                entity.CompanyId = request.CompanyId;
                entity.DateCreated = DateTime.Now;
                entity.LastUpdated = DateTime.Now;
                entity.CreatedBy = request.CompanyId;
                entity.IsExchange = false;
                entity.Source = 0;
                _jobPositionRepository.Add(entity);
                _jobPositionRepository.UnitOfWork.Commit();
            }
            catch (Exception ex)
            {
                response.Exception = ex;
            }
            return response;
        }
        #endregion

        #region Update
        public UpdateJobPositionResponse UpdateJobPosition(UpdateJobPositionRequest request)
        {
            var response = new UpdateJobPositionResponse();
            try
            {
                var jobPosition = request.JobPositionForm.CopyItem<IJobPositionCommand, JobPosition>();
                var entity = _jobPositionRepository.Get(request.JobPositionForm.Id);
                entity.JobTitle = jobPosition.JobTitle;
                entity.Category = jobPosition.Category;
                entity.JobType = jobPosition.JobType;
                entity.DepartmentId = jobPosition.DepartmentId;
                entity.UseDepartmentAddress = jobPosition.UseDepartmentAddress;
                entity.Wants = jobPosition.Wants;
                entity.Location = jobPosition.Location;
                entity.Responsibilities = jobPosition.Responsibilities;
                entity.Major = jobPosition.Major;
                entity.EducationLevel = jobPosition.EducationLevel;
                entity.YearsOfExperience = jobPosition.YearsOfExperience;
                entity.Language = jobPosition.Language;
                entity.LanguageLevel = jobPosition.LanguageLevel;
                entity.MinAge = jobPosition.MinAge;
                entity.MaxAge = jobPosition.MaxAge;
                entity.Gender = jobPosition.Gender;
                entity.Qualifications = jobPosition.Qualifications;
                entity.SalaryRange = jobPosition.SalaryRange;
                entity.MonthlySalary = jobPosition.MonthlySalary;
                entity.IsOpenSalaryRange = jobPosition.IsOpenSalaryRange;
                entity.Welfare = jobPosition.Welfare;
                entity.Contact = jobPosition.Contact;
                entity.Tel = jobPosition.Tel;
                entity.Fax = jobPosition.Fax;
                entity.Email = jobPosition.Email;
                entity.IsReceivedEmail = jobPosition.IsReceivedEmail;
                entity.Address = jobPosition.Address;
                entity.PostalCode = jobPosition.PostalCode;
                entity.SortOrder = jobPosition.SortOrder;
                entity.RecruiteGraduates = jobPosition.RecruiteGraduates;
                entity.Status = jobPosition.Status;
                entity.StartDate = jobPosition.StartDate;
                entity.EndDate = jobPosition.EndDate;
                entity.Reposted = jobPosition.Reposted;
                entity.LastUpdated = DateTime.Now;
                _jobPositionRepository.Modify(entity);
                _jobPositionRepository.UnitOfWork.Commit();
            }
            catch (Exception ex)
            {
                response.Exception = ex;
            }
            return response;
        }
        #endregion

        #region GetById
        public GetByIdResponse GetById(GetByIdRequest request)
        {
            var jobPostion = _jobPositionRepository.Get(request.Id);
            var viewModel = jobPostion.CopyItem<JobPosition, JobPositionViewModel>();
            return new GetByIdResponse() { ViewModel = viewModel };
        }
        #endregion

        #region SearchList
        public SearchListResponse SearchList(SearchListRequest request)
        {
            var response = new SearchListResponse();
            try
            {
                IPagedList<JobPosition> list = null;
                Specification<JobPosition> specification = null;
                switch (request.JobPositionStatus)
                {
                    case JobQueryStatus.All:
                        specification = JobPositionSpecifications.GetByCompany(request.CompanyId) &&
                            JobPositionSpecifications.GetByDeleted(false) &&
                            JobPositionSpecifications.GetByKeyword(request.Keyword);
                        list = _jobPositionRepository.GetPagedList(request.PageIndex, request.PageSize, specification, x => x.DateCreated, false);
                        break;
                    case JobQueryStatus.New:
                        specification = JobPositionSpecifications.GetByCompany(request.CompanyId) &&
                            JobPositionSpecifications.GetByStatus(JobPositionStatus.New) &&
                            JobPositionSpecifications.GetByDeleted(false) &&
                            JobPositionSpecifications.GetByKeyword(request.Keyword);

                        list = _jobPositionRepository.GetPagedList(request.PageIndex, request.PageSize, specification, x => x.DateCreated, false);
                        break;
                    case JobQueryStatus.Active:
                        specification = JobPositionSpecifications.GetByCompany(request.CompanyId) &&
                            JobPositionSpecifications.GetByStatus(JobPositionStatus.Active) &&
                            JobPositionSpecifications.GetByDeleted(false) &&
                            JobPositionSpecifications.GetByKeyword(request.Keyword);

                        list = _jobPositionRepository.GetPagedList(request.PageIndex, request.PageSize, specification, x => x.SortOrder ?? 0, true);
                        break;
                    case JobQueryStatus.Pause:
                        specification = JobPositionSpecifications.GetByCompany(request.CompanyId) &&
                            JobPositionSpecifications.GetByStatus(JobPositionStatus.Pause) &&
                            JobPositionSpecifications.GetByDeleted(false) &&
                            JobPositionSpecifications.GetByKeyword(request.Keyword);

                        list = _jobPositionRepository.GetPagedList(request.PageIndex, request.PageSize, specification, x => x.StartDate, false);
                        break;
                    case JobQueryStatus.Closed:
                        SetOverdueToClosed(request.CompanyId);
                        specification = JobPositionSpecifications.GetByCompany(request.CompanyId) &&
                            JobPositionSpecifications.GetByStatus(JobPositionStatus.Closed) &&
                            JobPositionSpecifications.GetByDeleted(false) &&
                            JobPositionSpecifications.GetByKeyword(request.Keyword);

                        list = _jobPositionRepository.GetPagedList(request.PageIndex, request.PageSize, specification, x => x.Reposted, false);
                        break;
                    case JobQueryStatus.Deleted:
                        specification = JobPositionSpecifications.GetByCompany(request.CompanyId) &&
                            JobPositionSpecifications.GetByDeleted(true) &&
                            JobPositionSpecifications.GetByKeyword(request.Keyword);
                        list = _jobPositionRepository.GetPagedList(request.PageIndex, request.PageSize, specification, x => x.LastUpdated, false);
                        break;
                }

                var listItemModelList = list.Select(x => new JobPositionListItemModel()
                {
                    ItemChecked = false,
                    DepartmentName = x.Department != null ? x.Department.DepartmentName : String.Empty,
                    EndDate = x.EndDate.ToString(_dateFormat),
                    Id = x.Id,
                    JobTitle = x.JobTitle,
                    Reposted = x.Reposted.HasValue ? x.Reposted.Value.ToString(_dateFormat) : String.Empty,
                    Status = x.Status,
                    Deleted = x.Deleted,
                    Address = x.Address,
                    SortOrder = x.SortOrder,
                    StartDate = x.StartDate.HasValue ? x.StartDate.Value.ToString(_dateFormat) : String.Empty,
                    DateCreated = x.DateCreated.ToString(_dateFormatTime),
                    DateDeleted = x.LastUpdated.ToString(_dateFormatTime),
                });
                response.ListItemModelList = new PagedList<JobPositionListItemModel>(listItemModelList, list.PageIndex, list.PageSize, list.TotalCount);
            }
            catch (Exception ex)
            {
                response.Exception = ex;
            }
            return response;
        }

        private void SetOverdueToClosed(Guid companyId)
        {
            var overdueList = _jobPositionRepository.AllMatching(JobPositionSpecifications.GetOverdueWithOutClosed()).ToList();
            (overdueList as List<JobPosition>).ForEach(x =>
            {
                x.Status = (int)JobPositionStatus.Closed;
                _jobPositionRepository.Modify(x);
            });
            _jobPositionRepository.UnitOfWork.Commit();
        }

        #endregion

        #region 上线
        public PostResponse Post(PostRequest request)
        {
            var response = new PostResponse();
            try
            {
                var entity = _jobPositionRepository.Get(request.Id);
                if (entity.Company.RemainingQuantity <= 0) 
                {
                    throw new Exception("剩余职位发布个数为0，无法发布");
                }
                if (entity.Status != (int)JobPositionStatus.Pause)
                {
                    entity.StartDate = DateTime.Now.Date;
                    entity.EndDate = DateTime.Now.Date.AddDays(30);
                }
                entity.Reposted = DateTime.Now;
                entity.Status = (int)JobPositionStatus.Active;
                entity.LastUpdated = DateTime.Now;
                _jobPositionRepository.Modify(entity);
                _jobPositionRepository.UnitOfWork.Commit();
            }
            catch (Exception ex)
            {
                response.Exception = ex;
            }
            return response;
        }
        #endregion

        #region 暂停
        public PauseResponse Pause(PauseRequest request)
        {
            var response = new PauseResponse();
            try
            {
                var entity = _jobPositionRepository.Get(request.Id);
                entity.Status = (int)JobPositionStatus.Pause;
                entity.LastUpdated = DateTime.Now;
                _jobPositionRepository.Modify(entity);
                _jobPositionRepository.UnitOfWork.Commit();
            }
            catch (Exception ex)
            {
                response.Exception = ex;
            }
            return response;
        }
        #endregion

        #region 刷新
        public RefreshResponse Refresh(RefreshRequest request)
        {
            var response = new RefreshResponse();
            try
            {
                var entity = _jobPositionRepository.Get(request.Id);
                entity.Reposted = DateTime.Now;
                entity.LastUpdated = DateTime.Now;
                _jobPositionRepository.Modify(entity);
                _jobPositionRepository.UnitOfWork.Commit();
            }
            catch (Exception ex)
            {
                response.Exception = ex;
            }
            return response;
        }
        #endregion

        #region 删除
        public DeleteResponse Delete(DeleteRequest request)
        {
            var response = new DeleteResponse();
            try
            {
                var entity = _jobPositionRepository.Get(request.Id);
                entity.Deleted = true;
                entity.LastUpdated = DateTime.Now;
                entity.Status = (int)JobPositionStatus.Closed;
                _jobPositionRepository.Modify(entity);
                _jobPositionRepository.UnitOfWork.Commit();
            }
            catch (Exception ex)
            {
                response.Exception = ex;
            }
            return response;
        }
        #endregion

        #region 还原
        public RestoreResponse Restore(RestoreRequest request)
        {
            var response = new RestoreResponse();
            try
            {
                var entity = _jobPositionRepository.Get(request.Id);
                entity.Deleted = false;
                entity.LastUpdated = DateTime.Now;
                entity.Status = (int)JobPositionStatus.New;
                _jobPositionRepository.Modify(entity);
                _jobPositionRepository.UnitOfWork.Commit();
            }
            catch (Exception ex)
            {
                response.Exception = ex;
            }
            return response;
        }
        #endregion

        #region 修改排序号
        public ChangeSortOrderResponse ChangeSortOrder(ChangeSortOrderRequest request)
        {
            var response = new ChangeSortOrderResponse();
            try
            {
                var entity = _jobPositionRepository.Get(request.Id);
                entity.SortOrder = request.SortOrder;
                _jobPositionRepository.Modify(entity);
            }
            catch (Exception ex)
            {
                response.Exception = ex;
            }
            return response;
        }
        #endregion
    }
}
